package club.babyf.springai.agent.function;

import club.babyf.lbs.entity.amap.req.GeoCodeGeoParameterDto;
import club.babyf.lbs.entity.amap.req.WeatherInfoParameterDto;
import club.babyf.lbs.entity.amap.res.GeoCodeDto;
import club.babyf.lbs.entity.amap.res.GeoCodeGeoDto;
import club.babyf.lbs.entity.amap.res.WeatherInfoDto;
import club.babyf.lbs.entity.amap.res.WeatherLiveDto;
import club.babyf.lbs.service.LbsService;
import club.babyf.springai.agent.annotation.Agent;
import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Description;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.function.Function;

@Slf4j
@Agent
@Service
@Description("天气函数")
@RequiredArgsConstructor
public class WeatherFunction implements Function<WeatherFunction.Request, WeatherFunction.Response> {

    private final LbsService lbsService;

    /**
     * 天气函数请求
     *
     * @param location 城市位置
     * @param unit     温度单位
     */
    @JsonInclude(Include.NON_NULL)
    @JsonClassDescription("天气函数请求")
    public record Request(
            @JsonProperty(required = true, value = "location") @JsonPropertyDescription("城市位置") String location,
            @JsonProperty(required = true, value = "unit") @JsonPropertyDescription("温度单位") Unit unit) {

    }

    /**
     * 天气函数响应
     *
     * @param weather       天气现象（汉字描述）
     * @param temperature   实时气温，单位：摄氏度
     * @param winddirection 风向描述
     * @param windpower     风力级别，单位：级
     * @param humidity      空气湿度
     * @param reporttime    数据发布的时间
     * @param unit          温度单位
     */
    public record Response(String weather, String temperature,
                           String winddirection, String windpower,
                           String humidity, String reporttime,
                           Unit unit) {

    }

    @Override
    public Response apply(Request request) {
        // 当前城市位置
        String location = request.location();
        // 温度单位
        Unit unit = request.unit();
        log.info("获取天气信息，位置：{}，温度单位：{}", location, unit);

        // 获取城市编码
        GeoCodeGeoParameterDto geoCodeGeoParameterDto = new GeoCodeGeoParameterDto();
        geoCodeGeoParameterDto.setAddress(location);
        GeoCodeGeoDto geoCodeGeoDto = lbsService.geoCodeGeo(geoCodeGeoParameterDto);
        if (geoCodeGeoDto == null) {
            return new Response("0", "0", "0", "0", "0", "0", unit);
        }
        List<GeoCodeDto> geocodes = geoCodeGeoDto.getGeocodes();
        if (geocodes == null || geocodes.isEmpty()) {
            return new Response("0", "0", "0", "0", "0", "0", unit);
        }
        GeoCodeDto geoCodeDto = geocodes.get(0);
        String adcode = geoCodeDto.getAdcode();

        // 获取天气信息
        WeatherInfoParameterDto weatherInfoParameterDto = new WeatherInfoParameterDto();
        weatherInfoParameterDto.setCity(adcode);
        WeatherInfoDto weatherInfoDto = lbsService.weatherInfo(weatherInfoParameterDto);
        if (weatherInfoDto == null) {
            return new Response("0", "0", "0", "0", "0", "0", unit);
        }
        List<WeatherLiveDto> lives = weatherInfoDto.getLives();
        if (lives == null || lives.isEmpty()) {
            return new Response("0", "0", "0", "0", "0", "0", unit);
        }
        lives.forEach(weatherLiveDto -> log.info("天气信息：{}", weatherInfoDto));
        WeatherLiveDto weatherLiveDto = lives.get(0);

        // 返回天气信息
        return new Response(weatherLiveDto.getWeather(), weatherLiveDto.getTemperature(), weatherLiveDto.getWinddirection(),
                weatherLiveDto.getWindpower(), weatherLiveDto.getHumidity(), weatherLiveDto.getReporttime(), unit);
    }

    /**
     * 温度单位.
     */
    public enum Unit {

        /**
         * 公制的
         * Celsius.
         */
        C("metric"),

        /**
         * 英制的
         * Fahrenheit.
         */
        F("imperial");

        /**
         * Human readable unit name.
         */
        public final String unitName;

        Unit(String text) {
            this.unitName = text;
        }

    }

}
